package org.xiaojl.xcloud.tools.gateway.filter.pre;

import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.xiaojl.xcloud.tools.gateway.RpcResult;
import org.xiaojl.xcloud.tools.gateway.config.LimitRateProperties;
import org.xiaojl.xcloud.tools.gateway.kit.FilterKit;
import org.xiaojl.xcloud.tools.gateway.kit.JsonKit;

import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/**  
 * <p>Title: LimitRateFilter</p>  
 *
 * <p>Description: 限流过滤器</p>  
 *
 * @author jilong.xiao  
 * @date 2018年5月7日  
 */
@Component
public class LimitRateFilter extends ZuulFilter {
	private static final Logger log = LoggerFactory.getLogger(LimitRateFilter.class);
	@Autowired
	private LimitRateProperties limitRateProperties;
	@Autowired(required=false)
	@Qualifier("longRedisTemplate")
	private RedisTemplate<String, Long> redisTemplate;
	
	//单节点限流
	public static volatile RateLimiter rateLimiter = null;
	
	@PostConstruct
	public void init(){
		rateLimiter = RateLimiter.create(limitRateProperties.getSingleLimitRate());
	}
	
	@Override
	public boolean shouldFilter() {
		return FilterKit.isFilterFlag(RequestContext.getCurrentContext());
	}

	@Override
	public Object run() {
		RequestContext context = RequestContext.getCurrentContext();
//		String serviceId = context.get("serviceId")==null?"":context.get("serviceId")+"";
//		System.err.println("serviceId："+serviceId);
		Double clusterLimitRate = limitRateProperties.getClusterLimitRate();
		if(clusterLimitRate > 0){ //集群限流
			try {
				Long currentSecond = System.currentTimeMillis()/1000;
				String key = "xcloud-cluster-limit-rate-"+currentSecond;
				if(!redisTemplate.hasKey(key)){
					//设置：过期100秒，值为0
					redisTemplate.opsForValue().set(key, 0L, 100, TimeUnit.SECONDS);
				}
				Long increment = redisTemplate.opsForValue().increment(key, 1);
				if(log.isDebugEnabled()){
					log.debug(String.format("集群限流阀值[%s]，当前并发流量[%s]", clusterLimitRate, increment));
				}
				if(increment > clusterLimitRate){
					RpcResult result = RpcResult.fail("当前负载太高，请稍后重试", "", null);
					context.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
					context.setResponseStatusCode(500);// 返回错误码  
					FilterKit.setFilterFlag(context,false);
					FilterKit.setRespBody(context,  JsonKit.toJson(result));
				    return null;
				}
			} catch (Exception e) {
//				log.error("集群限流出现异常：",e);
				log.error("集群限流出现异常："+e.getLocalizedMessage());
				
				//执行单节点限流逻辑
				doSingleLimitRate();
			}
		}
		
		//不限流
		return null;
	}

	/**  
	 * <p>Title: doSingleLimitRate</p>  
	 * <p>Description: 单节点限流</p>  
	 */ 
	private void doSingleLimitRate() {
		//集群不限流 或者 集群限流出现异常，都进入单节点限流
		Double singleLimitRate = limitRateProperties.getSingleLimitRate();
		if(singleLimitRate > 0){
			if(log.isDebugEnabled()){
				log.debug(String.format("单节点限流阀值[%s]", rateLimiter.getRate()));
			}
			//单节点限流
			double acquire = rateLimiter.acquire();
		}
	}

	@Override
	public String filterType() {
		return FilterConstants.PRE_TYPE;
	}

	@Override
	public int filterOrder() {
		return 7;
	}

}
